{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"modal","title":"Modal (Radix)","description":"Modal component for react-easy-modals with Radix Dialog.","dependencies":["react-easy-modals"],"registryDependencies":["dialog"],"files":[{"path":"src/registry/radix/modal.tsx","content":"\"use client\";\n\nimport { createContext, useContext, useRef, useState } from \"react\";\nimport { useBeforeClose, useModal, useModals } from \"react-easy-modals\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogOverlay,\n  DialogPortal,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/components/ui/dialog\";\n\ntype ModalContextValue = {\n  onAnimationEnd?: () => void;\n};\n\nconst ModalContext = createContext<ModalContextValue>({});\n\nconst ModalClose = DialogClose;\nconst ModalDescription = DialogDescription;\nconst ModalFooter = DialogFooter;\nconst ModalHeader = DialogHeader;\nconst ModalOverlay = DialogOverlay;\nconst ModalPortal = DialogPortal;\nconst ModalTitle = DialogTitle;\nconst ModalTrigger = DialogTrigger;\n\ntype ModalContentProps = React.ComponentProps<typeof DialogContent>;\n\nfunction ModalContent({\n  children,\n  className,\n  onAnimationEnd,\n  ...props\n}: ModalContentProps) {\n  const ctx = useContext(ModalContext);\n\n  return (\n    <DialogContent\n      className={cn(className)}\n      onAnimationEnd={(...e) => { onAnimationEnd?.(...e); ctx.onAnimationEnd?.() }}\n      {...props}\n    >\n      {children}\n    </DialogContent>\n  );\n}\n\ntype ModalRootProps = {\n  children: React.ReactNode;\n} & Omit<React.ComponentProps<typeof Dialog>, \"open\" | \"onOpenChange\">;\n\nfunction Modal({ children, ...dialogProps }: ModalRootProps) {\n  const modal = useModal();\n  const modals = useModals();\n  const [isVisible, setIsVisible] = useState(true);\n  const canClose = useRef(false);\n  const closableVariable = useRef<Parameters<typeof modal.close>[0]>(undefined);\n\n  const currentModalIndex = modals.stack.findIndex((m) => m.id === modal.id);\n  const isTopModal = modal.isNested || currentModalIndex === modals.stack.length - 1;\n  const modalIsHidden = !modal.isNested && currentModalIndex !== -1 && !isTopModal;\n\n  useBeforeClose<Parameters<typeof modal.close>[0]>((closeValue) => {\n    closableVariable.current = closeValue;\n    setIsVisible(false);\n    return canClose.current;\n  });\n\n  function handleOpenChange(value: boolean) {\n    if (!value && isTopModal) {\n      setIsVisible(false);\n    }\n  }\n\n  function handleAnimationEnd() {\n    if (!isVisible) {\n      canClose.current = true;\n      modal.close(closableVariable.current);\n      closableVariable.current = undefined;\n    }\n  }\n\n  return (\n    <ModalContext.Provider value={{ onAnimationEnd: handleAnimationEnd }}>\n      <Dialog\n        open={isVisible && !modalIsHidden}\n        onOpenChange={handleOpenChange}\n        {...dialogProps}\n      >\n        {children}\n      </Dialog>\n    </ModalContext.Provider>\n  );\n}\n\nexport {\n  Modal,\n  ModalClose,\n  ModalContent,\n  ModalDescription,\n  ModalFooter,\n  ModalHeader,\n  ModalOverlay,\n  ModalPortal,\n  ModalTitle,\n  ModalTrigger,\n};\n","type":"registry:ui"}],"type":"registry:ui"}